package cn.tedu.emqx.demo.emqx;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;

import java.nio.charset.StandardCharsets;

/**
 * 这是一个要交给mqttClient连接对象使用的回调类
 * 包含一个底层连接和emqx通信的4个回调时间点
 */
@Slf4j
public class MyMqttCallback implements MqttCallbackExtended {

    private final MqttClient mqttClient;

    public MyMqttCallback(MqttClient mqttClient){
        this.mqttClient = mqttClient;
    }
    /**
     * 回调时机: 客户端mqttClient成功建立与emqx服务端连接关系时调用
     * boolean reconnect: true表示本次连接是重连,false表示第一次连接
     * String serverUri: 实际连接的地址
     */
    @Override
    public void connectComplete(boolean reconnect, String serverURI) {
        if(reconnect){
            log.info("自动重连成功,borker服务端地址:{}",serverURI);
        }else{
            log.info("首次连接成功,borker服务端地址:{}",serverURI);
        }
        // 利用当前回调类所属的客户端,进行连接成功之后的主题订阅 如果当前回调类所属客户端没有订阅任何主题
        // 不可能消费主题的消息
        try {
            mqttClient.subscribe("topic03");
            mqttClient.subscribe("$share/test/topic02");
        } catch (MqttException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 回调时机: mqttClient连接断开时调用
     * Throwable cause: 连接断开原因
     * 如果设置了setAutomaticReconnect(true).自动重连,否则这个代码 手动处理重新连接
     */
    @Override
    public void connectionLost(Throwable throwable) {
        log.info("连接断开,原因:{}",throwable.getMessage());
    }
    /**
     * 回调时机: mqttClient通过订阅主题 获取到消息的时候 所以这个方法中应该包含消费逻辑
     * String topic: 消息来源主题
     * MqttMessage message: 消息对象(payLoad,qos retain)
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) {
        log.info("收到消息,来源topic:{},消息内容:{}",topic,
                new String(message.getPayload(), StandardCharsets.UTF_8));
    }
    /**
     * 回调时机: mqttClient投递发送消息的时候 接收到服务端反馈确认成功的 消息发送成功调用
     * 但是只有在QOS>0的时候才有效 因为  QOS=0 客户端不关心成功失败.
     * IMqttDeliveryToken token: 包含消息ID等上下文信息 原始消息就在token里
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        // 可以从token获得发送的原始消息
        String body = null;
        try{
            MqttMessage message = token.getMessage();
            body = new String(message.getPayload(),StandardCharsets.UTF_8);
        }catch (Exception e){
            log.error("获取原始消息失败",e);
        }
        log.info("消息投递完成,消息ID:{},消息原始内容:{}",token.getMessageId(),body);
    }
}
